﻿
using System;

using System.Collections;
using System.Data;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using SQLDiagConfiguration.Properties;

namespace SQLDiagConfiguration
{
    /// <summary>
    /// This class provides the functionality to enable Perfmon Collection
    /// and to specify which Perfmon counters will be collected
    /// </summary>
    public partial class PerfmonOptionsPage : BasePage
    {
        #region Constructor
        public PerfmonOptionsPage(DiagInfoObject obj)
        {
            DiagInfo = obj;
            InitializeComponent();
        }
        #endregion Constructor
        
        #region Page specific override methods
        /// <summary>
        /// This override loads the basic controls, populates the TreeView control
        /// and then enables or disables the controls based on the Perfmon Collection checkbox state
        /// </summary>
        public override void LoadState()
        {
            PopulateTemplatesBasedOnVersion();
            base.LoadState();
            LoadPerfMonCounterTree();
            bool enable = chkPerfMon.Checked;
            txtPerfMonMaxFileSize.Enabled = enable;
            cbPerfmonInterval.Enabled = enable;
            tvPerfMonCounters.Enabled = enable;
            cbPerfmonTemplates.Enabled = enable;

        }
        /// <summary>
        /// This override add the saving of the information contained in the TreeView control
        /// </summary>
        public override void SaveState()
        {
            base.SaveState();
            SavePerfMonCounterTree();
        }
        public override void LoadControlText()
        {
            base.LoadControlText();
            chkPerfMon.Text = Resources.strchkPerfMon;
            lblPerfmonMaxFileSize.Text = Resources.strlblPerfmonMaxFileSize;
            lblPerfmonPollingInterval.Text = Resources.strlblPerfmonPollingInterval;
            lblPerfmonTemplate.Text = Resources.strlblPerfmonTemplate;
        }
        #endregion Page specific override methods

        #region Event Handlers
        /// <summary>
        /// This event handler manages parent checkboxes base on the presence or absence of child checkboxes 
        /// being checked. When no child checkboxes are selected, we clear the parent checkbox.
        /// Likewise, when a child checkbox is checked, we automatically check the parent checkbox.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvPerfMonCounters_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Parent == null)
            { 
                foreach (TreeNode child in e.Node.Nodes)
                {
                    child.Checked = e.Node.Checked;
                }
            }
        }
        /// <summary>
        /// This event handler is responsible for enabling/disabling other controls
        /// based on the whether or not the Perfmon Collector checkbox is checked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkPerfMon_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox cb = (CheckBox)sender;
            bool clicked = cb.Checked;
            txtPerfMonMaxFileSize.Enabled = clicked;
            cbPerfmonInterval.Enabled = clicked;
            tvPerfMonCounters.Enabled = clicked;
            cbPerfmonTemplates.Enabled = (clicked && cbPerfmonTemplates.Items.Count > 0); 
        }
        private void cbPerfmonTemplates_SelectedIndexChanged(object sender, EventArgs e)
        {
            tvPerfMonCounters.Nodes.Clear();
            if (cbPerfmonTemplates.SelectedItem != null)
            {
                TemplateComboBoxInfoObject o = cbPerfmonTemplates.SelectedItem as TemplateComboBoxInfoObject;
                DataSet tempDataSet = new DataSet();
                tempDataSet.ReadXml(o.FullName);
                tempDataSet.DataSetName = "Replace";
                tempDataSet.Locale = CultureInfo.CurrentCulture;
                PopulateNodes(tempDataSet);
                tempDataSet.Dispose();   
            }
        }
        #endregion Event Handlers

        #region Helper Functions
        /// <summary>
        /// This method is responsible for populating the TreeView with all Perfmon Counters as specified
        /// in the configuration file, and setting the checked state appropriately
        /// </summary>
        private void LoadPerfMonCounterTree()
        {
            tvPerfMonCounters.ShowLines = true;
            tvPerfMonCounters.CheckBoxes = true;
            tvPerfMonCounters.Nodes.Clear();
            // Get a list of Perfmon Counters to process. This node list is rooted at the PerfmonObject level
            PopulateNodes(DiagInfo.SQLDiagConfigDataSet);

        }
       private void PopulateNodes(DataSet ds)
        {
            tvPerfMonCounters.Nodes.Clear();
            DiagInfo.PerfmonObjects.Clear();
            int rowNumber = 0;
            DataTable counters = ds.Tables[Resources.strPerfmonObject];
            DataRelation dr = ds.Relations[Resources.strCounterRelation];
            if (ds.DataSetName == "Replace")
            {
                 UpdateNodes(ds, Resources.strPerfmonObject, Resources.strPerfmonCounter,Resources.strCounterRelation,Resources.strPerfmonObjectID);
            }
 
           foreach (DataRow r in counters.Rows)
            {
                string objectName = r[Resources.strName].ToString();
                PerfmonObjectInfoObject pio = new PerfmonObjectInfoObject(objectName);
                DiagInfo.PerfmonObjects.Add(pio);
                 foreach(DataRow childRow in r.GetChildRows(dr))
                {
                    PerfmonCounterInfoObject c = new PerfmonCounterInfoObject();
                    c.ParentObj = pio;
                    c.Name = childRow[Resources.strName].ToString();
                    c.RowNumber = rowNumber;
                    c.Enabled = Convert.ToBoolean(childRow[Resources.strEnabled],CultureInfo.CurrentCulture);
                    rowNumber++;
                     // must account for some config files having duplicate counters...
                    if (!pio.Children.Contains(c.Name))
                    {
                        pio.Children.Add(c.Name, c);
                    }
                }
            }
            foreach (object obj in DiagInfo.PerfmonObjects)
            {
                PerfmonObjectInfoObject parent = obj as PerfmonObjectInfoObject;
                TreeNode objectName = tvPerfMonCounters.Nodes.Add(parent.ObjectName);

                int checkedEvents = 0;
                foreach (DictionaryEntry c in parent.Children)
                {
                    PerfmonCounterInfoObject child = c.Value as PerfmonCounterInfoObject;
                    TreeNode t = objectName.Nodes.Add(child.Name);
                    t.Tag = child.RowNumber;
                    t.Checked = child.Enabled;
                    if(t.Checked == true)
                    {
                        checkedEvents++;
                    }
                }
                if (checkedEvents == parent.Children.Count)
                {
                    objectName.Checked = true;
                }
            }
       }

        /// <summary>
        /// This method is responsible for iterating the TreeView and persisting all counters to 
        /// the configuration file
        /// </summary>
        public void SavePerfMonCounterTree()
        {
            //Iterate through the tree using the tag information to persist the checked state of each node
            //The outer loop persists the Counter object's checked state
            foreach (TreeNode counter in tvPerfMonCounters.Nodes)
            {
                //The inner loop persists the child counter's checked state
                foreach (TreeNode childCounter in counter.Nodes)
                {
                    int rowNumber = Convert.ToInt32(childCounter.Tag,CultureInfo.CurrentCulture);
                    DiagInfo.SQLDiagConfigDataSet.Tables[Resources.strPerfmonCounter].Rows[rowNumber][Resources.strEnabled] = childCounter.Checked ? Resources.strTrue : Resources.strFalse;
                }
            }
        }
        public void PopulateTemplatesBasedOnVersion()
        {
            try
            {
                cbPerfmonTemplates.Items.Clear();
                string dir = Resources.strBasePerfmonTemplatePath;
                string templateDir = (DiagInfo.Version.Length == 1) ? DiagInfo.Version : DiagInfo.Version.Substring(0, 2);
                foreach (string fileName in Directory.EnumerateFileSystemEntries(dir + templateDir, Resources.strXMLExtention, SearchOption.TopDirectoryOnly))
                {
                    int index = fileName.LastIndexOf(Resources.strBackSlash,StringComparison.CurrentCulture);
                    string file = fileName.Substring(index + 1);
                    TemplateComboBoxInfoObject tio = new TemplateComboBoxInfoObject(file, fileName);
                    cbPerfmonTemplates.Items.Add(tio);
                }
                if (cbPerfmonTemplates.Items.Count == 0)
                {
                    cbPerfmonTemplates.Enabled = false;
                }
            }
            catch (UnauthorizedAccessException UAEx)
            {
                Console.WriteLine(UAEx.Message);
            }
            catch (PathTooLongException PathEx)
            {
                Console.WriteLine(PathEx.Message);
            }
            cbPerfmonTemplates.DisplayMember = Resources.strFileName;
            cbPerfmonTemplates.ValueMember = Resources.strFullName;
        }
        #endregion Helper Functions

        private void PerfmonOptionsPage_Load(object sender, EventArgs e)
        {
            this.cbPerfmonTemplates.SelectedIndexChanged += new System.EventHandler(this.cbPerfmonTemplates_SelectedIndexChanged);
        }
    }
}
